package com.fingard.dsp.bank.directbank.alipay01;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayUserAgreementPageSignRequest;
import com.alipay.api.request.AlipayUserAgreementQueryRequest;
import com.alipay.api.request.AlipayUserAgreementUnsignRequest;
import com.alipay.api.response.AlipayUserAgreementPageSignResponse;
import com.alipay.api.response.AlipayUserAgreementQueryResponse;
import com.alipay.api.response.AlipayUserAgreementUnsignResponse;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.bankInterface.IEntrust;
import com.fingard.dsp.bank.reqrespobj.entrust.*;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import net.sf.json.JSONObject;

import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * 支付宝纯签约
 */
public class ALIPAY01Entrust extends ALIPAY01Base implements IEntrust {
    /**
     * 参考文档：https://opendocs.alipay.com/apis/api_2/alipay.user.agreement.page.sign
     * <p>
     * alipay.user.agreement.page.sign(支付宝个人协议页面签约接口)
     * 支持用户在支付宝页面完成支付宝代扣协议的签约，目前只支付宝钱包H5页面场景。
     * <p>
     *
     * @param p_req
     * @return
     */
    @Override
    public RetAtsEntrust submitEntrust(ReqEntrust p_req) {
        RetAtsEntrust retAts = new RetAtsEntrust(p_req);

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req.ownAct, "unifiedorder");
            if (actItem != null) {
                JSONObject alipayJsonRequest = new JSONObject();

                alipayJsonRequest.put("product_code", "GENERAL_WITHHOLDING");
                alipayJsonRequest.put("personal_product_code", "");
                alipayJsonRequest.put("sign_scene", "INDUSTRY");
                alipayJsonRequest.put("external_agreement_no", p_req.authCode);
                alipayJsonRequest.put("third_party_type", "PARTNER");
                String month = DateHelper.getDifferMonths(Format.Date8Format.parse(p_req.timeStart), Format.Date8Format.parse(p_req.timeExpire)) + "m";
                alipayJsonRequest.put("sign_validity_period", month);

                JSONObject zm_auth_params = new JSONObject();
                zm_auth_params.put("buckle_app_id", actItem.appId);
                zm_auth_params.put("buckle_merchant_id", actItem.merchantId);
                alipayJsonRequest.put("zm_auth_params", zm_auth_params);

                JSONObject prod_params = new JSONObject();
                prod_params.put("auth_biz_params", p_req.description);
                alipayJsonRequest.put("prod_params", prod_params);
                alipayJsonRequest.put("promo_params", "");

                JSONObject access_params = new JSONObject();
                access_params.put("channel", "ALIPAYAPP");
                alipayJsonRequest.put("access_params", access_params);

                JSONObject sub_merchant = new JSONObject();
                sub_merchant.put("sub_merchant_id", actItem.merchantId);
                sub_merchant.put("sub_merchant_name", p_req.oppActName);
                sub_merchant.put("sub_merchant_service_name", "");
                sub_merchant.put("sub_merchant_service_description", p_req.description);
                alipayJsonRequest.put("sub_merchant", sub_merchant);

                JSONObject device_params = new JSONObject();
                device_params.put("device_id", bankFront.termid);
                device_params.put("device_name", bankFront.name);
                device_params.put("device_type", "");
                alipayJsonRequest.put("device_params", device_params);
                alipayJsonRequest.put("merchant_process_url", actItem.notifyURL);

                JSONObject identity_params = new JSONObject();
                identity_params.put("user_name", p_req.oppActName);
                identity_params.put("cert_no", p_req.certNumber);
                identity_params.put("identity_hash", "");
                identity_params.put("sign_user_id", "");
                alipayJsonRequest.put("identity_params", identity_params);
                alipayJsonRequest.put("agreement_effect_type", "DIRECT");
                alipayJsonRequest.put("user_age_range", "");

                JSONObject period_rule_params = new JSONObject();
                period_rule_params.put("period_type", "DAY");
                period_rule_params.put("period", DateHelper.getDifferDays(Format.Date8Format.parse(p_req.timeStart), Format.Date8Format.parse(p_req.timeExpire)));
                period_rule_params.put("execute_time", Format.Date10Format.format(p_req.getTimeStart()));
                String singleLimit = getBankConfig().getMapValueByKey("contractKeyMapping", "singleLimit");
                if (StringHelper.isNullOrEmpty(singleLimit)) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "缺失配置节点'singleLimit'或值为空!";
                    return retAts;
                }
                period_rule_params.put("single_amount", singleLimit);
                String monthAmtLimit = getBankConfig().getMapValueByKey("contractKeyMapping", "monthAmtLimit");
                if (StringHelper.isNullOrEmpty(monthAmtLimit)) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "缺失配置节点'monthAmtLimit'或值为空!";
                    return retAts;
                }
                period_rule_params.put("total_amount", monthAmtLimit);
                String total_payments = getBankConfig().getMapValueByKey("contractKeyMapping", "countLimit");
                if (StringHelper.isNullOrEmpty(total_payments)) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "缺失配置节点'countLimit'或值为空!";
                    return retAts;
                }
                period_rule_params.put("total_payments", total_payments);
                alipayJsonRequest.put("period_rule_params", period_rule_params);
                alipayJsonRequest.put("allow_huazhi_degrade", "true");

                String bizContent = JSON.toJSONString(alipayJsonRequest);
                bizContent = bizContent.replaceAll("\\\\\\\\", "");

                AlipayUserAgreementPageSignRequest request = new AlipayUserAgreementPageSignRequest();
                TreeMap<String, String> signMapParams = new TreeMap<String, String>();

                signMapParams.put("app_id", actItem.appId);
                signMapParams.put("method", "alipay.trade.app.pay");
                signMapParams.put("format", "JSON");
                signMapParams.put("charset", getCharset());
                String signType = "RSA2";
                boolean useSignType = getBankConfig().getValueAsBool("useSignType");
                if (useSignType) {
                    signType = actItem.signType;
                }
                signMapParams.put("sign_type", signType);
                String timestamp = Format.DateTimeFormat.format(new Date());
                signMapParams.put("timestamp", timestamp);
                signMapParams.put("version", "1.0");
                signMapParams.put("notify_url", actItem.notifyURL);
                signMapParams.put("biz_content", bizContent);

                String mapStr = "";
                Iterator<Map.Entry<String, String>> it = signMapParams.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry<String, String> entry = it.next();
                    mapStr += entry.getKey() + ":" + entry.getValue() + "\r\n";
                }
                WriteBankLogLn("待签名MAP:\r\n" + mapStr);

                String signData = AlipaySignature.getSignContent(signMapParams);
                WriteBankLogLn2("待签名原始数据:" + signData);

                String signature = "";
                if ("RSA2".equalsIgnoreCase(signType)) {
                    signature = AlipaySignature.rsa256Sign(signData, actItem.ownKeyStorePath, getCharset());
                } else {
                    signature = AlipaySignature.rsaSign(signData, actItem.ownKeyStorePath, getCharset());
                }
                WriteBankLogLn2("本机生成签名:\r\n" + signature);
                signMapParams.put("sign", signature);
                request.setBizContent(convertMapToStr(signMapParams));
                AlipayClient alipayClient = new DefaultAlipayClient(bankFront.getUrl("h5EntrustWeb"), actItem.appId,
                        actItem.ownKeyStorePath, "json", getCharset(), actItem.oppCertFilePath, signType);

                WriteBankLogStep2(request.getBizContent());
                AlipayUserAgreementPageSignResponse response = alipayClient.pageExecute(request);
                WriteBankLogStep3(response.getBody());

                if (response != null) {
                    retAts.respCode = "0";
                    retAts.respInfo = response.getMsg();
                    if ("10000".equals(response.getCode())) {
                        retAts.result = StringHelper.joinNotEmpty("+", response.getCode(), response.getStatus());
                    } else {
                        retAts.result = StringHelper.joinNotEmpty("+", response.getCode(), response.getSubCode());
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = response.getBody();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号:[" + p_req.ownAct + "]商户配置信息,请检查'config/portfiles/" + p_req.reqHeader.bankCode + "/config.xml'中该账号相关商户配置节点是否配置正确!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return retAts;
    }

    /**
     * 参考文档：https://opendocs.alipay.com/apis/api_2/alipay.user.agreement.unsign
     * <p>
     * alipay.user.agreement.unsign(支付宝个人代扣协议解约接口)
     * 支付宝个人代扣协议解约接口
     * <p>
     *
     * @param p_req
     * @return
     */
    @Override
    public RetAtsDeEntrust submitDeEntrust(ReqDeEntrust p_req) {
        RetAtsDeEntrust retAts = new RetAtsDeEntrust(p_req);

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req.ownAct, "unifiedorder");
            if (actItem != null) {
                JSONObject alipayJsonRequest = new JSONObject();

                if (p_req.ownAct.matches("[0-9]{16}") && p_req.ownAct.startsWith("2088")) {
                    alipayJsonRequest.put("alipay_user_id", p_req.ownAct);
                } else {
                    alipayJsonRequest.put("alipay_logon_id", p_req.ownAct);
                }
                alipayJsonRequest.put("personal_product_code", "");
                alipayJsonRequest.put("sign_scene", "INDUSTRY");
                alipayJsonRequest.put("external_agreement_no", p_req.authCode);
                alipayJsonRequest.put("third_party_type", "PARTNER");
                alipayJsonRequest.put("agreement_no", p_req.channelAuthCode);
                alipayJsonRequest.put("extend_params", "");
                alipayJsonRequest.put("operate_type", "confirm");

                String bizContent = JSON.toJSONString(alipayJsonRequest);
                bizContent = bizContent.replaceAll("\\\\\\\\", "");

                AlipayUserAgreementUnsignRequest request = new AlipayUserAgreementUnsignRequest();
                TreeMap<String, String> signMapParams = new TreeMap<String, String>();

                signMapParams.put("app_id", actItem.appId);
                signMapParams.put("method", "alipay.trade.app.pay");
                signMapParams.put("format", "JSON");
                signMapParams.put("charset", getCharset());
                String signType = "RSA2";
                boolean useSignType = getBankConfig().getValueAsBool("useSignType");
                if (useSignType) {
                    signType = actItem.signType;
                }
                signMapParams.put("sign_type", signType);
                String timestamp = Format.DateTimeFormat.format(new Date());
                signMapParams.put("timestamp", timestamp);
                signMapParams.put("version", "1.0");
                signMapParams.put("notify_url", actItem.notifyURL);
                signMapParams.put("biz_content", bizContent);

                String mapStr = "";
                Iterator<Map.Entry<String, String>> it = signMapParams.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry<String, String> entry = it.next();
                    mapStr += entry.getKey() + ":" + entry.getValue() + "\r\n";
                }
                WriteBankLogLn("待签名MAP:\r\n" + mapStr);

                String signData = AlipaySignature.getSignContent(signMapParams);
                WriteBankLogLn2("待签名原始数据:" + signData);

                String signature = "";
                if ("RSA2".equalsIgnoreCase(signType)) {
                    signature = AlipaySignature.rsa256Sign(signData, actItem.ownKeyStorePath, getCharset());
                } else {
                    signature = AlipaySignature.rsaSign(signData, actItem.ownKeyStorePath, getCharset());
                }
                WriteBankLogLn2("本机生成签名:\r\n" + signature);
                signMapParams.put("sign", signature);
                request.setBizContent(convertMapToStr(signMapParams));
                AlipayClient alipayClient = new DefaultAlipayClient(bankFront.getUrl("deContract"), actItem.appId,
                        actItem.ownKeyStorePath, "json", getCharset(), actItem.oppCertFilePath, signType);

                WriteBankLogStep2(request.getBizContent());
                AlipayUserAgreementUnsignResponse response = alipayClient.pageExecute(request);
                WriteBankLogStep3(response.getBody());

                if (response != null) {
                    retAts.respCode = "0";
                    if ("10000".equals(response.getCode())) {
                        retAts.respInfo = response.getMsg();
                    } else {
                        retAts.respInfo = StringHelper.joinNotEmpty("+", response.getCode(), response.getSubCode());
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = response.getBody();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号:[" + p_req.ownAct + "]商户配置信息,请检查'config/portfiles/" + p_req.reqHeader.bankCode + "/config.xml'中该账号相关商户配置节点是否配置正确!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return retAts;
    }

    /**
     * 参考文档：https://opendocs.alipay.com/apis/api_2/alipay.user.agreement.query
     * <p>
     * alipay.user.agreement.query(支付宝个人代扣协议查询接口)
     * 支付宝个人代扣协议查询接口
     * <p>
     *
     * @param p_req
     * @return
     */
    @Override
    public RetAtsQueryEntrust queryEntrust(ReqQueryEntrust p_req) {
        RetAtsQueryEntrust retAts = new RetAtsQueryEntrust(p_req);

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req.ownAct, "unifiedorder");
            if (actItem != null) {
                JSONObject alipayJsonRequest = new JSONObject();

                alipayJsonRequest.put("personal_product_code", "");
                if (p_req.ownAct.matches("[0-9]{16}") && p_req.ownAct.startsWith("2088")) {
                    alipayJsonRequest.put("alipay_user_id", p_req.ownAct);
                } else {
                    alipayJsonRequest.put("alipay_logon_id", p_req.ownAct);
                }
                alipayJsonRequest.put("sign_scene", "INDUSTRY");
                alipayJsonRequest.put("external_agreement_no", p_req.authCode);
                alipayJsonRequest.put("third_party_type", "PARTNER");
                alipayJsonRequest.put("agreement_no", p_req.channelAuthCode);

                String bizContent = JSON.toJSONString(alipayJsonRequest);
                bizContent = bizContent.replaceAll("\\\\\\\\", "");

                AlipayUserAgreementQueryRequest request = new AlipayUserAgreementQueryRequest();
                TreeMap<String, String> signMapParams = new TreeMap<String, String>();

                signMapParams.put("app_id", actItem.appId);
                signMapParams.put("method", "alipay.trade.app.pay");
                signMapParams.put("format", "JSON");
                signMapParams.put("charset", getCharset());
                String signType = "RSA2";
                boolean useSignType = getBankConfig().getValueAsBool("useSignType");
                if (useSignType) {
                    signType = actItem.signType;
                }
                signMapParams.put("sign_type", signType);
                String timestamp = Format.DateTimeFormat.format(new Date());
                signMapParams.put("timestamp", timestamp);
                signMapParams.put("version", "1.0");
                signMapParams.put("notify_url", actItem.notifyURL);
                signMapParams.put("biz_content", bizContent);

                String mapStr = "";
                Iterator<Map.Entry<String, String>> it = signMapParams.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry<String, String> entry = it.next();
                    mapStr += entry.getKey() + ":" + entry.getValue() + "\r\n";
                }
                WriteBankLogLn("待签名MAP:\r\n" + mapStr);

                String signData = AlipaySignature.getSignContent(signMapParams);
                WriteBankLogLn2("待签名原始数据:" + signData);

                String signature = "";
                if ("RSA2".equalsIgnoreCase(signType)) {
                    signature = AlipaySignature.rsa256Sign(signData, actItem.ownKeyStorePath, getCharset());
                } else {
                    signature = AlipaySignature.rsaSign(signData, actItem.ownKeyStorePath, getCharset());
                }
                WriteBankLogLn2("本机生成签名:\r\n" + signature);
                signMapParams.put("sign", signature);
                request.setBizContent(convertMapToStr(signMapParams));
                AlipayClient alipayClient = new DefaultAlipayClient(bankFront.getUrl("qryContract"), actItem.appId,
                        actItem.ownKeyStorePath, "json", getCharset(), actItem.oppCertFilePath, signType);

                WriteBankLogStep2(request.getBizContent());
                AlipayUserAgreementQueryResponse response = alipayClient.pageExecute(request);
                WriteBankLogStep3(response.getBody());

                if (response != null) {
                    retAts.respCode = "0";
                    if ("10000".equals(response.getCode())) {
                        retAts.timeEntrustStart = response.getSignTime();
                        retAts.timeEntrustExpire = response.getInvalidTime();
                        retAts.planId = response.getDeviceId();
                        retAts.deEntrustWay = response.getPricipalType();
                        retAts.authCode = response.getAgreementNo();
                        retAts.channelAuthCode = response.getExternalAgreementNo();
                        // 1. TEMP：暂存，协议未生效过；  2. NORMAL：正常；  3. STOP：暂停
                        retAts.entrustState = response.getStatus();
                        retAts.openId = response.getZmOpenId();
                        retAts.appId = actItem.appId;
                    } else {
                        retAts.respInfo = StringHelper.joinNotEmpty("+", response.getCode(), response.getSubCode());
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = response.getBody();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号:[" + p_req.ownAct + "]商户配置信息,请检查'config/portfiles/" + p_req.reqHeader.bankCode + "/config.xml'中该账号相关商户配置节点是否配置正确!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }
        return retAts;
    }

}